#include "GW_ModProtocol.h"
#include "GW_Check.h"



GW_ModProtocol::GW_ModProtocol()
{
   this->sendLength = 0;
}

void GW_ModProtocol::beforeTimeout()
{

}
void GW_ModProtocol::afterTimeout()
{
}
void GW_ModProtocol::beforeGetByte()
{
}
void GW_ModProtocol::afterGetByte()
{
}

void GW_ModProtocol::Init()
{
   this->clearRecvBuf();
   this->clearSendBuf();
   this->state = MB_COMPLETE;
}

u8 GW_ModProtocol::GetFunctionID()
{
   return this->BReq.Cmd;
}

bool GW_ModProtocol::Matching(int length, u8 *request, u8 id, int direction)
{
   int i = 0, x = 0;
   u8 reqlen; u8 getlength = 0;
   u16 crccode = 0, getcrc = 0; //u16 crc=BReq.crc
   int cnt;
   //int addr = CGlobal::addr;
   int addr = id;
   if (cnt < 0)
   {
	  cnt = 0;
   }
   switch (direction)
   {
   case DIR_REQUEST:    //请求
	  {
		 reqlen = sizeof(this->BReq);
		 cnt = length;
		 for (i = 0; i <= cnt; i++)
		 {
			getlength = request[i + 4] << 8 | request[i + 5];
			if (getlength > MAXREGISTER)
			{
			   continue;
			}
			else
			{
			   switch (request[i + 1])
			   {
			   case MODBUS_IOREG:
			   case MODBUS_INPUTREG:
				  {
					 memmove((u8 *)&BReq, (request + i), reqlen);
					 crccode = crc16((u8 *)&BReq, reqlen - 2);
					 BReq.crc = BigLittleSwap16(BReq.crc);
					 if (crccode == BReq.crc)
					 {
						BReq.Cmd = request[i + 1];
						BReq.Length = BigLittleSwap16(BReq.Length);
						BReq.Register = BigLittleSwap16(BReq.Register);
						if (addr == BReq.Addr)
						{
						   if (cnt > MAXBUF)
						   {
							  cnt = MAXBUF;
						   }
						   memcpy(this->recvbuf, request, cnt);
						   return true;
						}
					 }
					 break;
				  }
			   case MODBUS_WRITEHOLD:
				  {
					 getlength = request[i + 6];
					 crccode = crc16(request + i, 7 + getlength);
					 BReq.crc = request[7 + getlength] << 8 | request[8 + getlength];
					 if (crccode = BReq.crc)
					 {
						memmove((u8 *)&BReq, (request + i), 7);
						BReq.Length = BigLittleSwap16(BReq.Length);
						BReq.Register = BigLittleSwap16(BReq.Register);
						if (addr == BReq.Addr)
						{
						   if (cnt > MAXBUF)
						   {
							  cnt = MAXBUF;
						   }
						   memcpy(this->recvbuf, request, cnt);
						   return true;
						}
					 }
					 break;
				  }
			   default:
				  {
					 continue;
				  }
			   }
			}
		 }
		 break;
	  }
   case DIR_REPONSE:        //回复
	  {
		 cnt = length;
		 for (i = 0; i <= cnt; i++)
		 {
			getlength = request[i + 2];
			if (getlength > MAXREGISTER)
			{
			   continue;
			}
			else
			{
			   switch (request[i + 1])
			   {
			   case MODBUS_IOREG:
			   case MODBUS_INPUTREG:
				  {
					 crccode = crc16(request, 3 + getlength);
					 getcrc = request[3 + getlength] << 8 | request[4 + getlength];
					 if (crccode == getcrc)
					 {
						memmove((u8 *)&this->BRes, (request + i), 4 + getlength);
						for (x = 0; x < getlength / 2; x++)
						{
						   this->BRes.dat[x] = BigLittleSwap16(this->BRes.dat[x]);
						}
						return true;
					 }
					 break;
				  }
			   default:
				  {
					 continue;
				  }
			   }
			}
		 }
	  }
   }

//   switch (this->recvbuf[1])
//   {
//   case MODBUS_INPUTREG:
//      {
//         for (i = 0; i <= cnt; i++)
//         {
//            memmove((u8 *)&BReq, (this->recvbuf + i), reqlen);
//            crccode = crc16((u8 *)&BReq, reqlen - 2);
//            BReq.crc = BigLittleSwap16(BReq.crc);
//            if (crccode == BReq.crc)
//            {
//               BReq.Length = BigLittleSwap16(BReq.Length);
//               BReq.Register = BigLittleSwap16(BReq.Register);
//               return true;
//            }
//         }
//         break;
//      }
//   }
   return false;
}

bool GW_ModProtocol::GetWaiting()
{
   return this->waiting;
}

u16 GW_ModProtocol::GetEffectRegCnt()
{
   return this->effectRegCnt;
}

u16 GW_ModProtocol::GetStartReg()
{
   return this->BReq.Register;
}




bool GW_ModProtocol::Recved(u8 *responseDat, int length, u8 id)
{
   u16 * dst,*src;
   bool ret = false;
   u16 crccode = 0, tmp = 0;
   int i = 0, x = 0;
   int addr = id;
   if (addr == this->BReq.Addr)
   {
	  this->startReg = this->BReq.Register;
	  switch (this->BReq.Cmd)
	  {
	  case MODBUS_IOREG:
	  case MODBUS_INPUTREG:
		 {
			this->sendbuf[0] = addr;
			this->sendbuf[1] = this->BReq.Cmd;
			//this->sendbuf[2] = (u8)this->BReq.Length * 2;
			dst = (u16 *)(this->sendbuf + 3);
			src = (u16 *)(responseDat + this->BReq.Register);
                        for (i = 0; i < this->BReq.Length * 2; i++)
                        {
                           if (i + this->BReq.Register * 2 >= length*2)
                           {
                              break;
                           }
                           this->sendbuf[3 + i] = responseDat[i + this->BReq.Register * 2];
                        }
//      		for (i = 0; i < this->BReq.Length; i++)
//      		{
//      		   if (i + this->BReq.Register >= length / 2)
//      		   {
//      			  break;
//      		   }
//      		   dst[i] = BigLittleSwap16(src[i]);
//      		}
			//i = i * 2;
			this->sendbuf[2] = (u8)i;
			crccode = crc16(this->sendbuf, i + 3);
			this->sendbuf[3 + i++] = crccode >> 8;
			this->sendbuf[3 + i++] = crccode & 0x00ff;
			this->sendLength = 3 + i;
			this->effectRegCnt = 0;
			break;
		 }
	  case MODBUS_WRITEHOLD:
		 {

			dst = (u16 *)(responseDat + BReq.Register * 2);
			src = (u16 *)(this->recvbuf + 7);
                        for (x = 0; x < BReq.Length * 2; x++)
                        {
                                     responseDat[BReq.Register * 2 + x] = this->recvbuf[7 + x];
                        }
//      		for (x = 0; x < BReq.Length; x++)
//      		{
//      		   dst[x] = BigLittleSwap16(src[x]);
//      		}
			memmove(this->sendbuf, this->recvbuf, 6);
			crccode = crc16(this->sendbuf, 6);
			this->sendbuf[6] = crccode >> 8;
			this->sendbuf[7] = crccode & 0x00ff;
			this->sendLength = 8;
			this->effectRegCnt = BReq.Length;
			break;
		 }

	  }
	  ret = true;
   }
   return ret;
}

bool GW_ModProtocol::Poll(int ch, int mode)
{
   switch (mode)
   {
   case MODBUS_BB:
	  {
		 this->BReq.Addr = ch;
		 this->BReq.Cmd = MODBUS_IOREG;
		 this->BReq.Register = BigLittleSwap16(ADDR_Value);
		 this->BReq.Length = BigLittleSwap16(3);
		 this->BReq.crc = BigLittleSwap16(crc16((u8 *)&this->BReq, sizeof(this->BReq) - 2));
		 memmove(this->sendbuf, (u8 *)&BReq, sizeof(this->BReq));
		 this->sendLength = sizeof(this->BReq);
		 break;
	  }
   case MODBUS_GW:
	  {
		 break;
	  }
   }
}

bool GW_ModProtocol::DataLoaded(u8 *responseDat, int length, int mode)
{
   bool ret = false;
   int i = 0, cnt = length;
   int getlength;
   getlength = this->BRes.Length;
   u16 *dst = (u16 *)responseDat;
   //u8 *src;
   //src = (u8 *)this->BRes.dat;
   switch (mode)
   {
   case MODBUS_BB:
	  {
		 //if (getlength>length)
		 //{
		 //	src += getlength - length;
		 //}
		 for (i = 0; i < length; i++)
		 {
			if (i >= getlength)
			{
			   dst[i] = 0;
			}
			else dst[i] = BigLittleSwap16(this->BRes.dat[i]);
		 }
		 return true;
		 break;
	  }
   }
   return false;
}

u8* GW_ModProtocol::GetSendMsg(int *len)
{
   *len = this->sendLength;
   return this->sendbuf;
   //buf = this->sendbuf;
   //return this->sendLength;
   //this->port->write((u8 *)&this->BRes, 5 + this->BRes.Length);
}
